﻿using System.Security.Claims;
using System.Text.Json;
using Microsoft.IdentityModel.JsonWebTokens;

namespace BPM.Web.Shared.Extensions;
internal static class TokenExtensions
{
    private static IEnumerable<Claim> GetClaims(string? token)
    {
        if (string.IsNullOrWhiteSpace(token))
        {
            return Enumerable.Empty<Claim>();
        }

        var jsonWebTokenHandler = new JsonWebTokenHandler();
        if (jsonWebTokenHandler.CanReadToken(token))
        {
            return jsonWebTokenHandler.ReadJsonWebToken(token).Claims;
        }
        else
        {
            return Enumerable.Empty<Claim>();
        }
    }

    /// <summary>
    /// 获取授权账票
    /// </summary>
    /// <param name="accessToken"></param>
    /// <param name="refreshToken"></param>
    /// <param name="expirDiff">60秒</param>
    /// <returns></returns>
    public static ClaimsPrincipal GetClaimsPrincipal(string? accessToken, string? refreshToken, uint expirDiff = 60)
    {
        var empty = new ClaimsPrincipal(new ClaimsIdentity());
        if (string.IsNullOrWhiteSpace(accessToken) || string.IsNullOrWhiteSpace(refreshToken))
        {
            return empty;
        }

        var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        var accessClaims = GetClaims(accessToken);
        var refreshClaims = GetClaims(refreshToken);
        var accessExpir = GerTokenExpir(accessClaims, "exp");
        var refreshExpir = GerTokenExpir(refreshClaims, "exp");

        //没有过期时间 或 刷新token与过期时间小于 expirDiff秒 内认为过期
        if (accessExpir == 0 || refreshExpir - now < expirDiff || refreshExpir == 0)
        {
            return empty;
        }

        var identity = new ClaimsIdentity(accessClaims, "jwt");
        identity.AddClaim(new("AccessToken", accessToken));
        identity.AddClaim(new("RefreshToken", refreshToken));
        identity.AddClaim(new("AccessExpir", accessExpir.ToString()));
        identity.AddClaim(new("RefreshExpir", refreshExpir.ToString()));
        return new ClaimsPrincipal(identity);
    }

    /// <summary>
    /// 获取过期时间
    /// </summary>
    /// <param name="claims"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    public static long GerTokenExpir(IEnumerable<Claim> claims, string type)
    {
        var expir = claims.FirstOrDefault(x => x.Type == type)?.Value;

        if (string.IsNullOrWhiteSpace(expir))
        {
            return 0;
        }

        if (long.TryParse(expir, out var val))
        {
            return val;
        }

        return 0;
    }

    /// <summary>
    /// 获取过期时间
    /// </summary>
    /// <param name="token"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    public static long GerTokenExpir(string? token, string type)
    {
        var expir = GetClaims(token).FirstOrDefault(x => x.Type == type)?.Value;

        if (string.IsNullOrWhiteSpace(expir))
        {
            return 0;
        }

        if (long.TryParse(expir, out var val))
        {
            return val;
        }

        return 0;
    }
}

